/*
 *    Copyright (c) 2018-2025, nart All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: nart
 */
package com.nai365.nart.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nai365.nart.blockchain.api.feign.RemoteDDCService;
import com.nai365.nart.blockchain.dto.CoinDDCDto;
import com.nai365.nart.blockchain.dto.CoinDDCResultDto;
import com.nai365.nart.common.core.constant.SecurityConstants;
import com.nai365.nart.common.core.es.SpuEsModel;
import com.nai365.nart.common.core.to.seckill.SeckillSessionWithSkusTO;
import com.nai365.nart.common.core.util.R;
import com.nai365.nart.common.core.vo.SeckillSkuVO;
import com.nai365.nart.common.core.vo.WareSkuVo;
import com.nai365.nart.product.constant.ProductStatusEnum;
import com.nai365.nart.product.entity.*;
import com.nai365.nart.product.mapper.SpuInfoMapper;
import com.nai365.nart.product.service.*;
import com.nai365.nart.product.vo.SpuInfoVo1;
import com.nai365.nart.product.vo.SpuSaveVo;
import com.nai365.nart.search.api.feign.SearchFeignService;
import com.nai365.nart.seckill.api.feign.SeckillFeignService;
import com.nai365.nart.ware.api.feign.WareFeignService;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * spu信息
 *
 * @author baogs
 * @date 2022-07-01 11:05:45
 */
@Service
@AllArgsConstructor
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoMapper, SpuInfo> implements SpuInfoService {

	@Autowired
	private SpuInfoDescService spuInfoDescService;

	@Autowired
	private SpuImagesService spuImagesService;

	private CategoryService  categoryService;

	SearchFeignService searchFeignService;

	BrandService brandService;
	RemoteDDCService remoteDDCService;

	SkuInfoService skuInfoService;

	WareFeignService wareFeignService;

	SeckillFeignService seckillFeignService;


	@Override
	public void savesupInfo(SpuSaveVo vo) {

		//1、保存spu基本信息：pms_spu_info
		SpuInfo spuInfoEntity = new SpuInfo();


		BeanUtils.copyProperties(vo,spuInfoEntity);

		Long catalogId = vo.getCatalogId();
		Category category = categoryService.getById(catalogId);
		Brand brand = brandService.getById(vo.getBrandId());
		spuInfoEntity.setCatalogName(category.getName());
		spuInfoEntity.setBrandLogo(brand.getLogo());
		this.saveBaseSpuInfo(spuInfoEntity);

		//2、保存spu的描述图片：pms_spu_info_desc
//		List<String> decript = vo.getDecript();

		SpuInfoDesc spuInfoDescEntity = new SpuInfoDesc();
		spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
		spuInfoDescEntity.setStory(vo.getStory());
		spuInfoDescEntity.setPurchaseNotes(vo.getPurchaseNotes());
		spuInfoDescService.save(spuInfoDescEntity);

		//3、保存spu的图片集：pms_spu_images
		List<String> images = vo.getImages();
		spuImagesService.saveImages(spuInfoEntity.getId(),images);


		//4、保存spu的积分信息：nart_sms--->sms_spu_bounds
		// TODO: 2021/4/21 优惠券相关后期完善
//		Bounds bounds = vo.getBounds();
//		SpuBoundTo spuBoundTo = new SpuBoundTo();
//		BeanUtils.copyProperties(bounds,spuBoundTo);
//		spuBoundTo.setSpuId(spuInfoEntity.getId());
//		R r = operationFeignService.saveSpuBounds(spuBoundTo,SecurityConstants.FROM_IN);
//
//		if (r.getCode() != 0) {
//			log.error("远程保存spu积分信息失败");
//		}


	}


	@Override
	public R up(Long spuId) {

		//1、查出当前spuId对应的所有sku信息,品牌的名字

		ArrayList<SpuEsModel> spus = new ArrayList<>();
		SpuInfo byId = getById(spuId);
		SpuEsModel spuEsModel = new SpuEsModel();

		BeanUtils.copyProperties(byId,spuEsModel);
		spus.add(spuEsModel);

		//TODO 5、将数据发给es进行保存：nart-search
		R r = searchFeignService.productStatusUp(spus, SecurityConstants.FROM_IN);

		if (r.getCode() == 0) {

			R r1 = seckillFeignService.saveSession(String.valueOf(spuId), SecurityConstants.FROM_IN);
			//远程调用成功
			//TODO 6、修改当前spu的状态
			boolean update = this.update(new LambdaUpdateWrapper<SpuInfo>().eq(SpuInfo::getId, spuId).set(SpuInfo::getPublishStatus, ProductStatusEnum.SPU_UP.getCode()));
			return R.ok(update);
		} else {
			//远程调用失败
			//TODO 7、重复调用？接口幂等性:重试机制
			return  R.failed("上架失败");
		}
	}

	@Override
	public boolean down(Long spuId){
		SpuInfo spuInfo = new SpuInfo();
		spuInfo.setId(spuId);
		spuInfo.setPublishStatus(0);

		R r1 = seckillFeignService.deleteSession(String.valueOf(spuId), SecurityConstants.FROM_IN);
		return this.updateById(spuInfo);
	}

	@Override
	public void saveBaseSpuInfo(SpuInfo spuInfoEntity) {

		this.baseMapper.insert(spuInfoEntity);

	}

	@Override
	public R upChain(Long spuId){


		SpuInfo byId = getById(spuId);
		CoinDDCDto coinDDCDto = new CoinDDCDto();
		BeanUtil.copyProperties(byId,coinDDCDto);
		coinDDCDto.setSpuId(byId.getId());
		coinDDCDto.setCopies((long)byId.getPublishQuantity());
		coinDDCDto.setUri(byId.getChainUrl());
		R coin = remoteDDCService.coin(coinDDCDto);

		if (coin.getCode() == 0 &&  coin.getData() != null) {

			CoinDDCResultDto data = JSONUtil.toBean(JSONUtil.toJsonStr(coin.getData()),CoinDDCResultDto.class);

			byId.setId(spuId);
			byId.setIsChain(1);
			byId.setTxHash(data.getTxHash());
			byId.setToken(data.getDdcid());
			byId.setTxId(data.getTxId());
			byId.setChainTime(LocalDateTime.now());
			updateById(byId);


			return R.ok(handlerSku(byId));
		}else {
			return coin;
		}


	}

	private boolean handlerSku(SpuInfo spuInfo) {
		Integer publishQuantity = spuInfo.getPublishQuantity();
		List<SkuInfo> collect = Stream.iterate(1, x -> ++x).parallel().limit(publishQuantity).map(item -> {

					DecimalFormat decimalFormat = new DecimalFormat("00000");
					String format = decimalFormat.format(item);
					SkuInfo skuInfo = new SkuInfo();
					BeanUtil.copyProperties(spuInfo, skuInfo);
					skuInfo.setSpuId(spuInfo.getId());
					skuInfo.setSkuCode(format);
					skuInfo.setSkuName(spuInfo.getSpuName());
					skuInfo.setSkuTitle(spuInfo.getSpuName());
					skuInfo.setSkuDesc(spuInfo.getSpuDescription());
					skuInfo.setSkuDefaultImg(spuInfo.getChainUrl());
					skuInfo.setPrice(spuInfo.getPublishPrice());
					skuInfo.setPublishStatus(0);
					skuInfo.setOwnerAddress("0xb96a0b55052c5d081eed749161b1dc2176b5a61f");
					return skuInfo;
				}
		).collect(Collectors.toList());

		boolean b = skuInfoService.saveBatch(collect);
		List<WareSkuVo> wareSkuVos = collect.parallelStream().map(item -> {
			WareSkuVo wareSkuVo = new WareSkuVo();
			wareSkuVo.setSkuId(item.getSkuId());
			wareSkuVo.setSkuName(item.getSkuName());
			wareSkuVo.setStock(1);
			return wareSkuVo;
		}).collect(Collectors.toList());
//一级市场不用保存库存
//		wareFeignService.saveWare(wareSkuVos,SecurityConstants.FROM_IN);

		return b;
	}


	@Override
	public IPage queryPageByCondtion(Page page, SpuInfo spuInfo, String key) {
		Long brandId = spuInfo.getBrandId();
		Long catalogId = spuInfo.getCatalogId();

		if (brandId != null &&brandId ==0){
			spuInfo.setBrandId(null);
		}
		if (catalogId != null &&catalogId ==0){
			spuInfo.setCatalogId(null);
		}

		LambdaQueryWrapper<SpuInfo> queryWrapper = Wrappers.lambdaQuery(spuInfo);

		if (!StringUtils.isEmpty(key)) {
			queryWrapper.and((wrapper) -> {
				wrapper.eq(SpuInfo::getId,key).or().like(SpuInfo::getSpuName,key);
			});
		}

		Integer publishStatus = spuInfo.getPublishStatus();
		if (publishStatus != null && publishStatus !=0) {
			queryWrapper.eq(SpuInfo::getPublishStatus,publishStatus);
		}
		Page page1 = page(page, queryWrapper);
		List<SpuInfo> records = page1.getRecords();
		List categoryIds = records.stream().map((catalog) -> {
			return catalog.getCatalogId();
		}).collect(Collectors.toList());

		if (categoryIds != null && categoryIds.size() > 0) {
			List<Category> list = categoryService.listByIds(categoryIds);
			List<SpuInfo> voList = records.stream().map((e ->{
				SpuInfoVo1 info = new SpuInfoVo1();
				BeanUtils.copyProperties(e,info);
				if (info.getCatalogId() != null && list != null){
					for (Category category: list){
						if (info.getCatalogId().longValue() == category.getCatId().longValue()){
							info.setCatalogName(category.getName());
						}
					}
				}
				return info;
			})).collect(Collectors.toList());
			page1.setRecords(voList);
		}

		return page1;
		//return page(page ,queryWrapper);
	}


	@Override
	public List<SeckillSessionWithSkusTO> getLates3DaySpuInfo() {


		//计算最近三天
		//查出这三天参与秒杀活动的商品
		List<SpuInfo> list = this.baseMapper.selectList(new QueryWrapper<SpuInfo>()
				.between("priority_sell_begin_time", startTime(), endTime()));

		if (list != null && list.size() > 0) {

			List<SeckillSessionWithSkusTO> collect = list.stream().map(session -> {
				SeckillSessionWithSkusTO seckillSessionWithSkusTO = new SeckillSessionWithSkusTO();
				seckillSessionWithSkusTO.setStartTime(session.getPrioritySellBeginTime());
				seckillSessionWithSkusTO.setId(session.getId());
				seckillSessionWithSkusTO.setEndTime(session.getPrioritySellBeginTime().plusHours(1));
				Long id = session.getId();
				List<SkuInfo> list1 = skuInfoService.list(new LambdaQueryWrapper<SkuInfo>().eq(SkuInfo::getSpuId, id));
				//查出sms_seckill_sku_relation表中关联的skuId

				List<SeckillSkuVO> collect1 = list1.parallelStream().map(item -> {
					SeckillSkuVO seckillSkuVO = new SeckillSkuVO();
					seckillSkuVO.setSkuId(item.getSkuId());
//					seckillSkuVO.setPromotionId(item.getSpuId());
					seckillSkuVO.setPromotionSessionId(item.getSpuId());
					seckillSkuVO.setSeckillCount(1);
					seckillSkuVO.setSeckillPrice(item.getPrice());
					seckillSkuVO.setSeckillLimit(1);
					return seckillSkuVO;
				}).collect(Collectors.toList());

//				List<SeckillSkuRelation> relationSkus = seckillSkuRelationService.list(new QueryWrapper<SeckillSkuRelation>()
//						.eq("promotion_session_id", id));
//				session.setRelationSkus(relationSkus);
				seckillSessionWithSkusTO.setRelationSkus(collect1);
				return seckillSessionWithSkusTO;
			}).collect(Collectors.toList());
			return collect;
		} else {
			return null;
		}
	}
	@Override
	public List<SeckillSessionWithSkusTO> getSpuInfoSessions(String spuId) {

		SpuInfo session = getOne(new LambdaQueryWrapper<SpuInfo>().eq(SpuInfo::getId, spuId));
		ArrayList<SeckillSessionWithSkusTO> lists = new ArrayList<>();
		if (session != null){
				SeckillSessionWithSkusTO seckillSessionWithSkusTO = new SeckillSessionWithSkusTO();
				seckillSessionWithSkusTO.setStartTime(session.getPrioritySellBeginTime());
				seckillSessionWithSkusTO.setId(session.getId());
				seckillSessionWithSkusTO.setEndTime(session.getPrioritySellBeginTime().plusHours(1));
				Long id = session.getId();
				List<SkuInfo> list1 = skuInfoService.list(new LambdaQueryWrapper<SkuInfo>().eq(SkuInfo::getSpuId, id));
				//查出sms_seckill_sku_relation表中关联的skuId

				List<SeckillSkuVO> collect1 = list1.parallelStream().map(item -> {
					SeckillSkuVO seckillSkuVO = new SeckillSkuVO();
					seckillSkuVO.setSkuId(item.getSkuId());
//					seckillSkuVO.setPromotionId(item.getSpuId());
					seckillSkuVO.setPromotionSessionId(item.getSpuId());
					seckillSkuVO.setSeckillCount(1);
					seckillSkuVO.setSeckillPrice(item.getPrice());
					seckillSkuVO.setSeckillLimit(1);
					return seckillSkuVO;
				}).collect(Collectors.toList());

				seckillSessionWithSkusTO.setRelationSkus(collect1);
				lists.add(seckillSessionWithSkusTO);
				return lists;
		} else {
			return null;
		}
	}





	/**
	 * 当前时间
	 * @return
	 */
	private String startTime() {
		LocalDate now = LocalDate.now();
		LocalTime min = LocalTime.MIN;
		LocalDateTime start = LocalDateTime.of(now, min);

		//格式化时间
		String startFormat = start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		return startFormat;
	}

	/**
	 * 结束时间
	 * @return
	 */
	private String endTime() {
		LocalDate now = LocalDate.now();
		LocalDate plus = now.plusDays(2);
		LocalTime max = LocalTime.MAX;
		LocalDateTime end = LocalDateTime.of(plus, max);

		//格式化时间
		String endFormat = end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		return endFormat;
	}



	/**
	 * 根据SkuId查询SPU信息
	 */
	@Override
	public JSONObject getBySkuId(Long skuId) {
		SkuInfo  skuInfo = skuInfoService.getById(skuId);
		SpuInfo  spuInfo = getById(skuInfo.getSpuId());
		Brand  brand = brandService.getById(spuInfo.getBrandId());
		spuInfo.setBrandName(brand.getName());
		JSONObject spuJson = JSONUtil.parseObj(spuInfo);
		spuJson.putOpt("skuCode", skuInfo.getSkuCode());
		spuJson.putOpt("token",skuInfo.getToken());
		return spuJson;
	}


}
